package main

import (
	"fmt"
	"jvm/classfile"
	"jvm/instructions"
	"jvm/instructions/base"
	"jvm/rtda"
	. "jvm/typedef"
)

func interpret(method *classfile.Method) {
	codeAttr := method.AttributeCode()
	thread := rtda.NewThread()
	frame := rtda.NewFrame(thread, codeAttr.MaxLocals(), codeAttr.MaxStack())
	thread.PushFrame(frame)
	defer catchErr(frame)
	run(thread, codeAttr.Code())
}
func run(thread *rtda.Thread, code []U1) {
	frame := thread.PopFrame()
	reader := base.NewCoderReader(code)
	for {
		pc := thread.PC()
		reader.SetPC(pc)
		inst := instructions.NewInst(reader.ReadU1())
		inst.ReadOperands(reader)

		frame.SetNextPC(reader.PC())

		inst.Execute(frame)
		thread.SetPC(frame.NextPC())
		//log
		fmt.Printf("pc:%2d inst:%T %v\n", pc, inst, inst)
	}

}
func catchErr(frame *rtda.Frame) {
	if r := recover(); r != nil {
		fmt.Printf("LocalVars:%v\n", frame.LocalVars())
		fmt.Printf("OPStack:%v\n", frame.OPStack())
		panic(r)
	}
}
